﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BackUpLibrary
{
    public class vpBackUp
    {
        private bool _IsSourceEmpty;
        private bool _IsDestinationEmpty;
        private string _fileName;
        private string _destFile;
        public vpBackUp()
        {       
        }

        public delegate void FileHandler();

        public event FileHandler FileCopy;

        protected void OnCopy()
        {
            if (FileCopy != null)
            {
                FileCopy();
            }
        }
        //copy file in progress
        public event EventHandler<CustomEventArgs> RaiseCustomEvent;


        /// <summary>
        /// Copy From
        /// </summary>
        public string Source { get; set; }
        /// <summary>
        /// Checks if the Source is empty
        /// </summary>
        public bool isSourceEmpty
        {
            get { return _IsSourceEmpty; }            
        }
        /// <summary>
        /// Checks if the Destination is empty
        /// </summary>
        public bool IsDestinationEmpty
        {
            get { return _IsDestinationEmpty; }        
        }
        /// <summary>
        /// Get / Set the file to search for
        /// </summary>
        public string FileType { get; set; }
        /// <summary>
        /// Copy To
        /// </summary>
        public string Destination { get; set; }

        /// <summary>
        /// Set a FileInfo type
        /// </summary>
        public vpBackUpFile SourceFile { get; set; }

        /// <summary>
        /// Set a FileInfo type
        /// </summary>
        public vpBackUpFile DestinationFile { get; set; }

        /// <summary>
        /// Checks if the source folder is valid
        /// </summary>
        /// <returns>True/False</returns>
        public bool isSourceValid()
        {
            if (String.IsNullOrEmpty(Source))
                throw new ArgumentException("Property cannot be null", "Source");

            if (String.IsNullOrEmpty(FileType))
                throw new ArgumentException("Property cannot be null", "FileType");

            try
            {
                IEnumerable<string> dirFiles = Directory.EnumerateFiles(Source, "*." + FileType);
                if(dirFiles.Any())
                { _IsSourceEmpty = false; }
                else { _IsSourceEmpty = true; }
                return true;
            }
            catch (Exception exception)
            {
                return false;
               // throw new IOException("Invalid source", exception);
            }
            
        }
        /// <summary>
        /// Checks if the destination folder is valid
        /// </summary>
        /// <returns>True/False</returns>
        public bool isDestinationValid()
        {
            if (String.IsNullOrEmpty(Destination))
                throw new ArgumentException("Property cannot be null", "Destination");
            try
            {
                IEnumerable<string> dirFiles = Directory.EnumerateFiles(Destination, "*.*");
                if (dirFiles.Any())
                { _IsDestinationEmpty = false; }
                else { _IsDestinationEmpty = true; }
                return true;
            }
            catch (Exception exception)
            {
                return false;
                //throw new IOException("Invalid Destination", exception);
            }

        }

        /// <summary>
        /// Copy all files base on the filter to destination. Files on destination will be override
        /// </summary>
        /// <returns>True/False</returns>
        public bool CopySourceToDestination()
        {
            try
            {
                string[] files = Directory.GetFiles(Source);
                if (files.Any())
                {
                    foreach (string s in files)
                    {
                        // Use static Path methods to extract only the file name from the path.
                        _fileName = System.IO.Path.GetFileName(s);
                        _destFile = System.IO.Path.Combine(Destination, _fileName);
                        File.Copy(s, _destFile, true);

                        FileCopy();
                        OnRaiseCustomEvent(new CustomEventArgs(s));
                    }

                    return true;
                }
                else
                    return false;

            
                
                
            }
            catch (Exception)
            {

                return false;
            }
            
        }

        public void CopyEverythingDirectory()
        {
            DirectoryCopy(Source, Destination, true);
        }

        private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
        {
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            // If the source directory does not exist, throw an exception.
            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory does not exist, create it.
            DirectoryInfo destDir = new DirectoryInfo(destDirName);
            //string root = destDir.Root.Name;
            //string sFolder = destDir.Name;
            //destDirName = root + sFolder + "\\" + dir.Name;
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }


            // Get the file contents of the directory to copy.
            FileInfo[] files = dir.GetFiles();

            foreach (FileInfo file in files)
            {
                // Create the path to the new copy of the file.
                string temppath = Path.Combine(destDirName, file.Name);

                // Copy the file.
                file.CopyTo(temppath, false);
                OnRaiseCustomEvent(new CustomEventArgs(file.Name));
            }

            // If copySubDirs is true, copy the subdirectories.
            if (copySubDirs)
            {

                foreach (DirectoryInfo subdir in dirs)
                {
                    // Create the subdirectory.
                    string temppath = Path.Combine(destDirName, subdir.Name);

                    // Copy the subdirectories.
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs);
                }
            }

        }

        protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
        {
            // Make a temporary copy of the event to avoid possibility of
            // a race condition if the last subscriber unsubscribes
            // immediately after the null check and before the event is raised.
            EventHandler<CustomEventArgs> handler = RaiseCustomEvent;

            // Event will be null if there are no subscribers
            if (handler != null)
            {
                // Format the string to send inside the CustomEventArgs parameter
                e.Message += String.Format(" at {0}", DateTime.Now.ToString());

                // Use the () operator to raise the event.
                handler(this, e);
            }
        }
    }

    public class CustomEventArgs : EventArgs
    {

        public CustomEventArgs(string s)
        {
            message = s;
        }

        private string message;

        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }

}
